home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS22.ADF / Garden / Garden.c < prev    next >
C/C++ Source or Header  |  1987-06-30  |  11KB  |  367 lines

  1. /*************************************************************************
  2. /* Garden.c - An "electronic wallpaper" amusement based on finite-state    **
  3. **        automata                        **
  4. **    ⌐ 1987, Kevin A. Bjorke                        **
  5. **    National Pixel Products, Valencia, CA 91355            **
  6. **    Nov 84, Nov 85, March 86, May 87                **
  7. *************************************************************************/
  8.  
  9. /*************************************************
  10. ** Compile under Lattice 3.10 like so:        **
  11. **    lc -b -r -v -qram: -M Garden        **
  12. **    blink with Garden.With            **
  13. ** Where file Garden.With contains:        **
  14. **    FROM lib:c.o sys:Garden.o        **
  15. **    TO sys:Garden                **
  16. **    LIB lib:amiga.lib lib:lc.lib        **
  17. **    MAP ram:Garden.map            **
  18. **    VERBOSE                    **
  19. **    PLAIN                    **
  20. **    SMALLCODE                **
  21. **    SMALLDATA                **
  22. **    NODEBUG                    **
  23. *************************************************/
  24.  
  25. #include <exec/types.h>
  26. #include <exec/nodes.h>
  27. #include <exec/lists.h>
  28. #include <intuition/intuition.h>
  29. #include <graphics/text.h>
  30.  
  31. #define SPAN 320         /* Number of Cell units */
  32. #define EMPTY 0          /* No cell here (in tube[][]) */
  33. #define CELL 1           /* Cell here */
  34. #define MINLINE   1      /* top (vertical) scanline */
  35. #define MAXLINE   200    /* bottom scanline */
  36.  
  37. #define SpanClip(a) ((a)<0)?(SPAN+(a)):(((a)>=SPAN)?((a)-SPAN):(a))
  38. #define SpanClip2(a) ((a)>=SPAN)?((a)-SPAN):(a)
  39.  
  40. /****************************************************************/
  41. /****** Misc Externs & IntuiStuff *******************************/
  42. /****************************************************************/
  43.  
  44. extern long GfxBase;
  45. extern long IntuitionBase;
  46. extern struct InputEvent *Intuition();
  47. extern struct Window *OpenWindow();
  48. extern struct Screen *OpenScreen();
  49.  
  50. /****************/
  51.  
  52. extern VOID AmiSetup();        /* forward declarations of functions below */
  53. extern VOID AmiCleanup();
  54. extern VOID Grow();
  55. extern VOID CellSetup();
  56. extern VOID DrawOld();
  57. extern UWORD Age();
  58. extern SHORT Event();
  59.  
  60. /****************************************************************/
  61. /********* IntuiJunk ********************************************/
  62. /****************************************************************/
  63.  
  64. struct TextAttr ROMFont8 = {
  65.     "topaz.font",8,0,0
  66. };
  67.  
  68. USHORT class = NULL;
  69. USHORT code;
  70. struct Window *wn = NULL;
  71. struct Screen *sc = NULL;
  72. struct RastPort *rp;
  73. struct ViewPort *vp;
  74. struct IntuiMessage *message;
  75.  
  76. /****************************************************************/
  77. /****************************************************************/
  78. /****************************************************************/
  79.  
  80. struct IntuiText MenText[3] = {
  81.     {19,1,JAM1,0,0,&ROMFont8,"About",NULL},
  82.     {17,1,JAM1,0,0,&ROMFont8,"Clear",NULL},
  83.     {15,1,JAM1,0,0,&ROMFont8,"Quit", NULL}
  84. };
  85.  
  86. struct MenuItem Quits = {
  87.     NULL, 0,18, 50,9, ITEMTEXT|ITEMENABLED|HIGHCOMP,
  88.     0L,(APTR)&MenText[2], NULL,'\0',NULL,0
  89. };
  90.  
  91. struct MenuItem Clear = {
  92.     &Quits,    0,9, 50,9, ITEMTEXT|ITEMENABLED|HIGHCOMP,
  93.     0L,(APTR)&MenText[1], NULL,'\0',NULL,0
  94. };
  95.  
  96. struct MenuItem About = {
  97.     &Clear,    0,0, 50,9, ITEMTEXT|ITEMENABLED|HIGHCOMP,
  98.     0L,(APTR)&MenText[0], NULL,'\0',NULL,0
  99. };
  100.  
  101. struct Menu Garden = {
  102.     NULL, 0,0, (7<<3),9,MENUENABLED|MIDRAWN,
  103.     "Garden",&About
  104. };
  105.  
  106. struct IntuiText ReqText[7] = {
  107.     {15,1,JAM2,10, 8,&ROMFont8,"GARDEN by Kevin Bjorke",&ReqText[1]},
  108.     { 6,1,JAM2,10,16,&ROMFont8,"⌐ 1987, National Pixel",&ReqText[2]},
  109.     {19,1,JAM2,18,24,&ROMFont8,"CIS:74756,464",        &ReqText[3]},
  110.     {31,1,JAM2,18,32,&ROMFont8,"PLink:OJS637",        &ReqText[4]},
  111.     {17,1,JAM2,18,40,&ROMFont8,"BIX:kbjorke",        NULL},
  112.     {13,1,JAM2,AUTOLEFTEDGE,AUTOTOPEDGE,&ROMFont8,"Okay",NULL},
  113.     {13,1,JAM2,AUTOLEFTEDGE,AUTOTOPEDGE,&ROMFont8,"Fine",NULL}
  114. };
  115.  
  116. UWORD GardenCMap[32] = {    /* Colors */
  117.     0x22D,0xFC2,0x9C0,0x4A0,0x360,0x7C0,0xA4A,0x4A0,
  118.     0x380,0x190,0x0A0,0x2B8,0x4AD,0x77E,0x2C4,0xB05,
  119.     0x5B0,0xB72,0x933,0x080,0xFFE,0x183,0x2C6,0x9D0,
  120.     0x777,0x4A0,0xD92,0xA4A,0xEE0,0x7C0,0xF83,0x77E
  121. };
  122.  
  123. /****************************************************************/
  124. /****** Screen **************************************************/
  125. /****************************************************************/
  126.  
  127. struct NewScreen ns = {
  128.     0,0,            /* start pos.*/
  129.     320,200,5,    /* width height depth (2 bit planes) */
  130.     3,0,            /* detail pen, block pen */
  131.     0,            /* ViewModes */
  132.     CUSTOMSCREEN,        /* Type */
  133.     &ROMFont8,        /* Font */
  134.     NULL,            /* Title */
  135.     NULL, NULL        /* Gadgets, CustomBitMap */
  136. };
  137.  
  138. /****************************************************************/
  139. /******** Window ************************************************/
  140. /****************************************************************/
  141.  
  142. struct NewWindow nw = {
  143.     0,0,320,200,
  144.     12,0,        /* detail, block pens */
  145.     MENUPICK,    /* IDCMPFlags */
  146.     BACKDROP|BORDERLESS|SMART_REFRESH|ACTIVATE,    /* Flags */
  147.     NULL,        /* FirstGadget */
  148.     NULL,        /* CheckMark */
  149.     NULL,        /* Title */
  150.     NULL,        /* Screen */
  151.     NULL,        /* CustomBitMap */
  152.     0,0,0,0,    /* sizing limits */
  153.     CUSTOMSCREEN
  154. };
  155.  
  156. /****************************************************************/
  157. /******* Gardening Variables ************************************/
  158. /****************************************************************/
  159.  
  160. UBYTE tube[2][SPAN];    /* cell reproduction happens here */
  161. UWORD new = 0;
  162. UWORD old = 1;
  163. SHORT CellColr = 0;
  164. SHORT ScanLine = -1;
  165.  
  166. /****************************************************************/
  167. /***** Execution Begins *****************************************/
  168. /****************************************************************/
  169.  
  170. VOID _main()
  171. {
  172.     ULONG Seconds, Micros;
  173.     AmiSetup();
  174.     CurrentTime(&Seconds,&Micros);
  175.     srand((unsigned)(Micros & 0xFFFF));
  176.     do {
  177.        if (ScanLine<MINLINE)
  178.           CellSetup();
  179.        else
  180.           Grow();
  181.        if(wn->UserPort->mp_SigBit) {
  182.           message = (struct IntuiMessage *)GetMsg(wn->UserPort);
  183.           if(message != NULL) {
  184.              class = message->Class;
  185.              code  = message->Code;
  186.              ReplyMsg(message);
  187.           }
  188.        }
  189.     } while(Event());
  190.     AmiCleanup();
  191. }
  192.  
  193. /****************************************************************/
  194. /****** IDCMP Filtering *****************************************/
  195. /****************************************************************/
  196.  
  197. SHORT Event()
  198. {
  199.     register UWORD u;
  200.     SHORT MNum, INum;
  201.     if (class == MENUPICK) {
  202.        class = NULL;
  203.        MNum = MENUNUM(code);
  204.        INum = ITEMNUM(code);
  205.        if ((MNum == 0)&&(INum == 2)) {
  206.           return(NULL);        /* byebye */
  207.        }
  208.        if ((MNum == 0)&&(INum == 1)) {
  209.           /* SetRast(rp,0);    */
  210.           for (u=0;u<200;u+=4) {
  211.              ScrollRaster(rp,0,-4,0,0,320,200);
  212.              WaitTOF();
  213.           }
  214.           ScanLine = -1;
  215.           return(2);
  216.        }
  217.        if ((MNum == 0)&&(INum == 0)) {
  218.           AutoRequest(wn,&ReqText[0],&ReqText[5],&ReqText[6],
  219.         NULL,NULL,(36+(22<<3)),85);
  220.           return(3);
  221.        }
  222.     }
  223.     class = NULL;
  224.     return(-1);
  225. }
  226.  
  227. /****************************************************************/
  228. /***** Main Action **********************************************/
  229. /****************************************************************/
  230.  
  231. VOID Grow()
  232. {
  233.     DrawOld();
  234.     if (Age() > 0) {
  235.        old = new;
  236.        new ^= 1;
  237.        --ScanLine;
  238.     } else {
  239.        ScanLine = -1;    /* force a CellSetup() */
  240.     }
  241. }
  242.  
  243. /****************************************************************/
  244. /****** Display Most-recent layer *******************************/
  245. /****************************************************************/
  246.  
  247. VOID DrawOld()
  248. {
  249.     UWORD CellCt;
  250.     Move(rp,0,ScanLine);
  251.     for (CellCt = 0; CellCt < SPAN; ++CellCt) {
  252.        if (tube[old][CellCt] == CELL)
  253.           WritePixel(rp,CellCt,ScanLine);
  254.     }
  255. }
  256.  
  257. /****************************************************************/
  258. /***** Make a Random Cell Line **********************************/
  259. /****************************************************************/
  260.  
  261. VOID CellSetup()
  262. {
  263.     register UWORD CellCt, j;
  264.     old = 0;
  265.     new = 1;
  266.     for (CellCt = 0; CellCt < SPAN; ++CellCt) {
  267.        if ((CellCt & 15) == 0)
  268.           j = rand();
  269.        tube[old][CellCt] = (j & 1);
  270.        j >>= 1;
  271.     }
  272.     CellColr = ++CellColr & 31;
  273.     SetAPen(rp,CellColr);
  274.     ScanLine = (MAXLINE-1);
  275. }
  276.  
  277. /****************************************************************/
  278. /***** Generate New Cells ***************************************/
  279. /****************************************************************/
  280.  
  281. /*****************************************************************
  282. ** Algorithm Notes:                        **
  283. ** This algorithm is extremely simple, and has little basis in    **
  284. ** real growth mechanisms, except perhaps those of lakeside    **
  285. ** algae. Instead, it's more akin to Conway's LIFE, but is only    **
  286. ** one-dimensional -- by saving the history as successive scan-    **
  287. ** lines, we get plantlike growths. The algorithm is this: scan **
  288. ** the local pixel and its four closest neighbors. If the the    **
  289. ** sum is 2 or 4, live. If not, die. Simple, eh?        **
  290. *****************************************************************/
  291.  
  292. UWORD Age()
  293. {
  294.     register UWORD nCells = 0;
  295.     register UWORD where;
  296.     register SHORT trail, nPals, CellCt;
  297.  
  298.     nPals = tube[old][SPAN-3] + tube[old][SPAN-2] + tube[old][SPAN-1] +
  299.         tube[old][0] + tube[old][1];    /* Solve LAST cell first */
  300.     for(CellCt=0; CellCt<SPAN; ++CellCt) {
  301.        trail = SpanClip(CellCt-3);        /* solve incrementally */
  302.        where = SpanClip2(CellCt+2);        /* never negative */
  303.        nPals += (tube[old][where]-tube[old][trail]);
  304.        if ((nPals==2)||(nPals==4)) {
  305.           tube[new][CellCt] = CELL;
  306.           ++nCells;
  307.        } else {
  308.           tube[new][CellCt] = EMPTY;
  309.        }
  310.     }
  311.     return(nCells);
  312. }
  313.  
  314. /****************************************************************/
  315. /******* Setup Screen *******************************************/
  316. /****************************************************************/
  317.  
  318. VOID AmiSetup()
  319. {
  320.     if ((GfxBase = OpenLibrary("graphics.library",LIBRARY_VERSION)) == NULL)
  321.        Exit(1);
  322.     if ((IntuitionBase = OpenLibrary("intuition.library",LIBRARY_VERSION)) ==
  323.         NULL) {
  324.        AmiCleanup();
  325.        Exit(1);
  326.     }
  327.     if ((sc = OpenScreen(&ns)) == NULL) {
  328.        AmiCleanup();
  329.        Exit(0);
  330.     }
  331.     nw.Screen = sc;
  332.     if ((wn = OpenWindow(&nw)) == NULL) {
  333.        AmiCleanup();
  334.        Exit(2);
  335.     }
  336.     rp = wn->RPort;
  337.     vp = &wn->WScreen->ViewPort;
  338.     LoadRGB4(vp,GardenCMap,32);
  339.     ShowTitle(sc,FALSE);
  340.     SetAPen(rp,1);
  341.     SetDrMd(rp,JAM1);
  342.     SetMenuStrip(wn,&Garden);
  343. }
  344.  
  345. /****************************************************************/
  346. /****************************************************************/
  347. /****************************************************************/
  348.  
  349. VOID AmiCleanup()
  350. {
  351.     if (wn != NULL) {
  352.        ClearMenuStrip(wn);
  353.        CloseWindow(wn);
  354.     }
  355.     if (sc != NULL)
  356.        CloseScreen(sc);
  357.     if (GfxBase != NULL)
  358.        CloseLibrary(GfxBase);
  359.     if (IntuitionBase != NULL)
  360.        CloseLibrary(IntuitionBase);
  361. }
  362.  
  363. /****************************************************************/
  364. /******************************************************** eof ***/
  365. /****************************************************************/
  366.  
  367.